package com.pokermind.dse.tcp.config;

import io.micrometer.core.instrument.MeterRegistry;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * TCP服务器配置类
 * 封装所有TCP服务器相关的配置参数
 * 
 * 配置项包括：
 * - 服务器基本配置（端口、线程数等）
 * - 网络参数配置（超时、缓冲区等）
 * - 协议配置（最大帧大小、心跳等）
 * - 性能优化配置（内存分配、Epoll等）
 * 
 * @author PokerMind Team
 */
@Configuration
@ConfigurationProperties(prefix = "pokermind.tcp")
public class TcpServerConfig {

    /**
     * 服务器配置
     */
    public static class Server {
        private int port = 8888;
        private String host = "0.0.0.0";
        private int bossThreads = 1;
        private int workerThreads = 0; // 0 = CPU核数 * 2
        private int maxConnections = 10000;
        private int soBacklog = 1024;
        private boolean soKeepalive = true;
        private boolean tcpNodelay = true;
        private boolean soReuseaddr = true;

        // Getters and Setters
        public int getPort() { return port; }
        public void setPort(int port) { this.port = port; }
        
        public String getHost() { return host; }
        public void setHost(String host) { this.host = host; }
        
        public int getBossThreads() { return bossThreads; }
        public void setBossThreads(int bossThreads) { this.bossThreads = bossThreads; }
        
        public int getWorkerThreads() { return workerThreads; }
        public void setWorkerThreads(int workerThreads) { this.workerThreads = workerThreads; }
        
        public int getMaxConnections() { return maxConnections; }
        public void setMaxConnections(int maxConnections) { this.maxConnections = maxConnections; }
        
        public int getSoBacklog() { return soBacklog; }
        public void setSoBacklog(int soBacklog) { this.soBacklog = soBacklog; }
        
        public boolean isSoKeepalive() { return soKeepalive; }
        public void setSoKeepalive(boolean soKeepalive) { this.soKeepalive = soKeepalive; }
        
        public boolean isTcpNodelay() { return tcpNodelay; }
        public void setTcpNodelay(boolean tcpNodelay) { this.tcpNodelay = tcpNodelay; }
        
        public boolean isSoReuseaddr() { return soReuseaddr; }
        public void setSoReuseaddr(boolean soReuseaddr) { this.soReuseaddr = soReuseaddr; }
    }

    /**
     * 协议配置
     */
    public static class Protocol {
        private int maxFrameSize = 65536; // 64KB
        private int readTimeout = 30;     // seconds
        private int writeTimeout = 30;    // seconds
        private boolean enableHeartbeat = true;
        private int heartbeatInterval = 30; // seconds

        // Getters and Setters
        public int getMaxFrameSize() { return maxFrameSize; }
        public void setMaxFrameSize(int maxFrameSize) { this.maxFrameSize = maxFrameSize; }
        
        public int getReadTimeout() { return readTimeout; }
        public void setReadTimeout(int readTimeout) { this.readTimeout = readTimeout; }
        
        public int getWriteTimeout() { return writeTimeout; }
        public void setWriteTimeout(int writeTimeout) { this.writeTimeout = writeTimeout; }
        
        public boolean isEnableHeartbeat() { return enableHeartbeat; }
        public void setEnableHeartbeat(boolean enableHeartbeat) { this.enableHeartbeat = enableHeartbeat; }
        
        public int getHeartbeatInterval() { return heartbeatInterval; }
        public void setHeartbeatInterval(int heartbeatInterval) { this.heartbeatInterval = heartbeatInterval; }
    }

    /**
     * 性能配置
     */
    public static class Performance {
        private boolean enableEpoll = true;
        private String allocatorType = "pooled"; // pooled or unpooled
        private String leakDetection = "simple"; // disabled, simple, advanced, paranoid

        // Getters and Setters
        public boolean isEnableEpoll() { return enableEpoll; }
        public void setEnableEpoll(boolean enableEpoll) { this.enableEpoll = enableEpoll; }
        
        public String getAllocatorType() { return allocatorType; }
        public void setAllocatorType(String allocatorType) { this.allocatorType = allocatorType; }
        
        public String getLeakDetection() { return leakDetection; }
        public void setLeakDetection(String leakDetection) { this.leakDetection = leakDetection; }
    }

    // 配置实例
    private Server server = new Server();
    private Protocol protocol = new Protocol();
    private Performance performance = new Performance();

    // Getters and Setters
    public Server getServer() { return server; }
    public void setServer(Server server) { this.server = server; }
    
    public Protocol getProtocol() { return protocol; }
    public void setProtocol(Protocol protocol) { this.protocol = protocol; }
    
    public Performance getPerformance() { return performance; }
    public void setPerformance(Performance performance) { this.performance = performance; }

    /**
     * 计算实际的Worker线程数
     */
    public int getActualWorkerThreads() {
        int workerThreads = server.getWorkerThreads();
        if (workerThreads <= 0) {
            return Runtime.getRuntime().availableProcessors() * 2;
        }
        return workerThreads;
    }

    /**
     * 检查是否可以使用Epoll（仅Linux系统支持）
     */
    public boolean canUseEpoll() {
        return performance.isEnableEpoll() && 
               System.getProperty("os.name").toLowerCase().contains("linux");
    }

    /**
     * 获取配置摘要信息（用于日志输出）
     */
    public String getConfigSummary() {
        return String.format(
            "TcpServer Config: %s:%d, boss=%d, worker=%d, maxConn=%d, protocol=%s, epoll=%s",
            server.getHost(),
            server.getPort(),
            server.getBossThreads(),
            getActualWorkerThreads(),
            server.getMaxConnections(),
            protocol.isEnableHeartbeat() ? "heartbeat" : "no-heartbeat",
            canUseEpoll() ? "enabled" : "disabled"
        );
    }

    /**
     * MeterRegistry Bean for Metrics
     */
    @Bean
    public MeterRegistry meterRegistry() {
        return io.micrometer.core.instrument.Metrics.globalRegistry;
    }
}
